/**
 * @author: Kapil Kashyap
 */
dropdown_plugin = (function($) {
	/* Global variables */
	var	pageItems = [],
		currentPage = 1,
		maximumNumberOfPages = 1,
		totalResults = null,
		startIndex = null,
		endIndex = null,
		paginationFooter = '',
		
		// default config
		config = {
			inputSelector: '', // mandatory
			inputContainerSelector: '', // mandatory
			baseCls: 'dropdown-container',
			dropdownCloseBtnCls: 'dropdown-container-close',
			itemsPerPage: 5,
			dropdownPosition: 'bottom',
			closeBtnPosition: 'right',
			template: null
		},
		initializeEvents = function() {
			$( '.' + config.baseCls + '-item' ).live('click', function() {
				$( this ).parentsUntil(null, config.inputContainerSelector).find( config.inputSelector ).val( $( this ).text() ).focus();
				dropdown_plugin.reset( $( this ).parentsUntil(null, config.inputContainerSelector) );
			});
			
			$( config.inputContainerSelector ).each(function() {
				$( this ).live('keydown', function(event) {
					var selectedItem = $( this ).find( '.' + config['item-selected-cls'] );
					
					if(selectedItem && selectedItem.length > 0) {
						if(event.keyCode == 38) {
							selectedItem.removeClass( config['item-selected-cls'] );
							if(selectedItem.prev().length > 0) {
								selectedItem.prev().addClass( config['item-selected-cls'] );
							}
							else {
								highlightLastItem();
							}
						}
						else if(event.keyCode == 40) {
							selectedItem.removeClass( config['item-selected-cls'] );
							if(selectedItem.next().length > 0 && selectedItem.next().hasClass(config.baseCls + '-item')) {
								selectedItem.next().addClass( config['item-selected-cls'] );
							}
							else {
								highlightFirstItem();
							}
						}
						else if(event.keyCode == 37) {
							$( this ).find( '.' + config.baseCls + '-footer-left-nav' ).click();
							highlightFirstItem();
						}
						else if(event.keyCode == 39) {
							$( this ).find( '.' + config.baseCls + '-footer-right-nav' ).click();
							highlightFirstItem();
						}
						else if(event.keyCode == 13) {
							$( this ).find( config.inputSelector ).val( $( '.' + config['item-selected-cls'] ).text() ).focus();
							dropdown_plugin.reset( $( this ) );
						}
					}
				});
				
				$( this ).find( config.inputSelector ).live('blur', function(event) {
					// remove the drop down
					dropdown_plugin.reset( $( this ).parent() );
				});
			});
			
			$( '.' + config.baseCls + '-footer-right-nav' ).live('click', function() {
				if(currentPage < maximumNumberOfPages) {
					currentPage++;
					$( this ).parentsUntil(null, '.' + config.baseCls).html( paginate( pageItems, config.itemsPerPage, currentPage ) );
					updateFooterInfo( $( this ).parentsUntil(null, config.inputContainerSelector) );
				}
				highlightFirstItem();
			});
			
			$( '.' + config.baseCls + '-footer-left-nav' ).live('click', function() {
				if(currentPage > 1) {
					currentPage--;
					$( this ).parentsUntil(null, '.' + config.baseCls).html( paginate( pageItems, config.itemsPerPage, currentPage ) );
					updateFooterInfo( $( this ).parentsUntil(null, config.inputContainerSelector) );
				}
				highlightFirstItem();
			});
			
			$( '.' + config.dropdownCloseBtnCls ).live('click', function() {
				$( this ).parent().find( config.inputSelector ).val( '' );
				dropdown_plugin.reset( $( this ).parent() );
			});
		},
		
		constructPaginationFooter = function() {
			paginationFooter = '<div class="' + config.baseCls + '-footer">';
				paginationFooter += '<div class="' + config.baseCls + '-footer-content">';
					paginationFooter += '<span class="' + config.baseCls + '-footer-left-nav">&lt;</span>';
					paginationFooter += '<span class="' + config.baseCls + '-footer-info"></span>';
					paginationFooter += '<span class="' + config.baseCls + '-footer-right-nav">&gt;</span>';
				paginationFooter += '</div>';
			paginationFooter += '</div>';
		},
		paginate = function(pageItems, itemsPerPage) {
			var threshold = itemsPerPage * currentPage,
				paginatedItems = [];
				
			maximumNumberOfPages = (pageItems.length % itemsPerPage > 0) 
									? Math.floor( pageItems.length / itemsPerPage ) + 1 
									: Math.floor( pageItems.length / itemsPerPage );
									
			totalResults = pageItems.length;
			
			$.each(pageItems, function(index, item) {
				if(index == (threshold - itemsPerPage)) {
					startIndex = index;
				}
				if(index >= (threshold - itemsPerPage) && index < threshold) {
					paginatedItems.push(item);
					endIndex = index;
				}
			});
			
			if(maximumNumberOfPages > 1) {
				paginatedItems.push(paginationFooter);
			}
			
			return paginatedItems.join( '' );
		},
		updateFooterInfo = function( baseCtnr ) {
			$( baseCtnr ).find( '.' + config.baseCls + '-footer-info' ).html( (startIndex + 1) + ' - ' + (endIndex + 1) + ' of ' + totalResults);
		},
		highlightFirstItem = function() {
			$( '.' + config.baseCls + '-item' ).first().addClass( config['item-selected-cls'] );
		},
		highlightLastItem = function() {
			$( '.' + config.baseCls + '-item' ).last().addClass( config['item-selected-cls'] );
		};
		
	return {
		initialize: function( _config ) {
			// extend the default config with the one passed in as an argument.
			$.extend(config, _config);
			
			if(!config.inputSelector || !config.inputContainerSelector) {
				var errorMsg = 'inputSelector and inputContainerSelector properties are mandatory in the config.';
				if(window.console) {
					console.error ? console.error( errorMsg ) : console.log( errorMsg );
				}
				else {
					alert( errorMsg );
				}
				return;
			}
			
			if(isNaN(config.itemsPerPage) || config.itemsPerPage <= 0) {
				config.itemsPerPage = 5;
			}
			
			config['item-selected-cls'] = config.baseCls + '-item-selected';
				
			// Check to see if template is included in the config then js-template plugin
			// should be available to construct template based HTML structures.
			if(config.template && !jsTemplate) {
				var errorMsg = 'js-template-plugin is required.';
				if(window.console) {
					console.error ? console.error( errorMsg ) : console.log( errorMsg );
				}
				else {
					alert( errorMsg );
				}
				return;
			}
			
			constructPaginationFooter();
			initializeEvents();
		},
		
		constructDropDown: function( items, useTemplate ) {
			if(items == null || items.length == 0) {
				dropdown_plugin.reset( $( event.srcElement ).parent() );
				return;
			};
			
			// IF : a template is available in the config then the user expects to build the HTML construct
			// using the template. The passed in items are in the required format for the jsTemplate to
			// construct the HTML Structure.
			// ELSE : the template is not available in the config then the user is expected to provide the
			// HTML construct in the items passed.
			// *** setting the built (using jsTemplate.constructHtml method) or passed items to the global variable.
			if(useTemplate) {
				pageItems = jsTemplate.constructHtml( config.template, items );
			}
			else {
				pageItems = items;
			}
			
			// reset the currentPage property
			currentPage = 1;
	
			if( pageItems ) {
				var $ctnr = $( event.srcElement ).parent().find( '.' + config.baseCls );
				if( $ctnr.length > 0 ) {
					$ctnr.html( '' );
					$ctnr.html( paginate( pageItems, config.itemsPerPage, currentPage ) );
				}
				else {
					var $dropdown_close_Btn = $('<div/>', {
						'class': config.dropdownCloseBtnCls,
						'html': '<div class="btn">X</div>'
					});
					$( event.srcElement ).parent().append( $dropdown_close_Btn );
					
					var $dropdown_container = $('<div/>', {
						'class': config.baseCls,
						'width': $( config.inputContainerSelector ).width(),
						'html': paginate( pageItems, config.itemsPerPage, currentPage )
					});
					$( event.srcElement ).parent().append( $dropdown_container );
				}
				
				updateFooterInfo( $( event.srcElement ).parent() );
				
				// position the drop down with respect to the input container
				$( $dropdown_container ).reposition($( event.srcElement ).parent(), config.dropdownPosition);
				$( $dropdown_close_Btn ).reposition($( event.srcElement ), config.closeBtnPosition);
				
				highlightFirstItem();
			}
		},
		
		reset: function( inputCtnr ) {
			inputCtnr.find( '.' + config.dropdownCloseBtnCls ).remove();
			inputCtnr.find( '.' + config.baseCls ).remove();
			currentPage = 1;
		}
	};
})(jQuery);